package com.netease.nimlib.fts.query;

import java.util.ArrayList;

public class Tokenizer {
	private static final boolean OUTPUT_LOG = false;
	
	private int types[];

	public Tokenizer() {
		initTypes();
	}

	/**
	 * -1 as 'space' terminate others, skip; 
	 * 0 continuous token; 
	 * 1 single token; 
	 * 2  中文汉字
	 */
	private void initTypes() {
		if (types != null) {
			return;
		}

		types = new int[0x80];
		int i = 0;
		for (i = 0x00; i <= 0x20; i++) {
			types[i] = -1;
		}
		for (i = 0x21; i <= 0x2F; i++) {
			types[i] = 1;
		}
		types[0x2A] = -1;
		for (i = 0x30; i <= 0x39; i++) {
			types[i] = 0;
		}
		for (i = 0x3A; i <= 0x40; i++) {
			types[i] = 1;
		}
		for (i = 0x41; i <= 0x5A; i++) {
			types[i] = 0;
		}
		for (i = 0x5B; i <= 0x60; i++) {
			types[i] = 1;
		}
		for (i = 0x61; i <= 0x7A; i++) {
			types[i] = 0;
		}
		for (i = 0x7B; i <= 0x7E; i++) {
			types[i] = 1;
		}
		for (i = 0x7F; i <= 0x7F; i++) {
			types[i] = -1;
		}
	}

	int getCharType(char c) {
		if (c >= 0x80) {
			return 2;
		} else {
			return types[c];
		}
	}

	/**
	 * 分词算法
	 */
	public ArrayList<String> getTokens(String input, boolean singleMode) {
		ArrayList<String> result = new ArrayList<>();
		int p = 0;
		int length = input.length();

		while (p < length) {
			int startOffset = -1; // 新token的起始位置
			char c;
			int flag = -1; // 0 英文 1 中文 -1 初始位置
			// 开始提取新的token
			while (p < length) {
				c = input.charAt(p);
				if (c < 0x80) {
					// 处理ASCII
					int config = types[c];
					if (config == 0) {
						// 处理连续字符token
						if (startOffset == -1) {
							startOffset = p; // 确定新的token的起始位置
							flag = 0;
						}
						if (flag == 1) {
							break; // 如果前面有中文token那么先提交前面的token
						}
						p++;
					} else if (config > 0) {
						// 处理单个字符token
						if (startOffset == -1) {
							startOffset = p++; // 确定新的token的起始位置
							flag = 0;
						}
						break; // 如果前面有token那么先提交前面的token，没有则提交当前单个字符token
					} else {
						// 处理空格等分隔符
						if (startOffset == -1) {
							// 前面没有token，直接处理下一个字符
							p++;
						} else {
							// 前面有token，先提交前面的token
							break;
						}
					}
				} else {
					if (singleMode) {
						// 处理单个中文汉字
						if (startOffset == -1) {
							// 前面没有token，确定新的token位置
							startOffset = p++;
							flag = 1;
						}
						break; // 如果前面有token那么先提交前面的token，没有则提交当前中文汉字的token
					} else {
						// 处理连续中文汉字
						if (startOffset == -1) {
							startOffset = p; // 确定新的token的起始位置
							flag = 1;
						}
						// 如果前面有英文token那么先提交前面的token
						if (flag == 0) {
							break;
						}
						p++;
					}
				}
			}

			// 提交token
			if (startOffset != -1) {
				result.add(new String(input.substring(startOffset, p)));
			}
		}
		
		// log
		if(OUTPUT_LOG) {
			System.out.println("---------tokenizer------------");
			System.out.println("tokenizer:" + input);
			for (String token : result) {
				System.out.println(token);
			}
			System.out.println("---------tokenizer------------");
		}
		
		return result;
	}

	/**
	 * ***************** Single instance *****************
	 */
	public static Tokenizer getInstance() {
		return InstanceHolder.instance;
	}

	public static class InstanceHolder {
		public final static Tokenizer instance = new Tokenizer();
	}
}
